import * as BABYLON from "babylonjs";
import type { Engine, Scene, Camera, ArcRotateCamera } from "babylonjs";
import Ground from "./World/Ground";
import Event from "./Event";



import Map from "../map/Map";
import Agv from "./World/Agv";
import Gui from "./Gui/Gui";
import { EE } from "../event";

export default class Base {
  public static base: Base;
  public canvas: HTMLCanvasElement;
  private engine: Engine;
  public map: Map;
  public scene: Scene;
  public agvObjOne: Agv;
  // public agvObjTwo: Agv
  // public agvObjThree: Agv
  private camera: ArcRotateCamera;
  private followCameraOne: Camera
  // private followCameraTwo: Camera
  // private followCameraThree: Camera

  public gui: Gui
  public ground: Ground
  // private light: Light;

  constructor(canvas: HTMLCanvasElement) {
    Base.base = this;
    this.map = new Map()

    this.canvas = canvas;
    this.engine = this.createEngine();
    this.scene = this.createScene();


    // this.camera = this.createFreeCamera();
    this.agvObjOne = new Agv('AGV1:10.13.32.11', { linkOffsetX: 100, linkOffsetY: -100 })
    // this.agvObjTwo = new Agv('AGV2:10.13.32.110', { linkOffsetX: 100, linkOffsetY: -200 })
    // this.agvObjThree = new Agv('AGV3:10.13.32.111', { linkOffsetX: 200, linkOffsetY: -200 })

    this.camera = this.createArcRotateCamera();
    this.followCameraOne = this.createFollowCamera(this.agvObjOne)

    // this.followCameraTwo = this.createFollowCamera(this.agvObjTwo)
    // this.followCameraThree = this.createFollowCamera(this.agvObjThree)

    // this.light = this.createDirectionalLight();
    this.createAxesHelper()
    this.initRender();
    this.initResizeEvent();

    this.ground = new Ground();
    new Event()
    this.gui = new Gui()
    // register eventemitter3 
    this.registerMoveX()


  }

  private createEngine() {
    // Load the 3D engine
    return new BABYLON.Engine(this.canvas, true, {
      preserveDrawingBuffer: true,
      stencil: true,
    });
  }

  private createScene() {
    // Create a basic BJS Scene object
    return new BABYLON.Scene(this.engine);
  }

  private createFollowCamera(agvObj: Agv) {
    const camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(agvObj.agv.position.x, 0, agvObj.agv.position.z), this.scene);
    // ztx agv
    camera.position = new BABYLON.Vector3(agvObj.agv.position.x, 20, agvObj.agv.position.z)
    // 旋转相机180度,这里很关键,后面遇到不同的地图,可能需要调整
    // camera.alpha += Math.PI;
    // 获取鼠标输入管理器
    camera.attachControl(true, false, 0); // The 3 here indicates that panning will be done with button 3
    // camera.parent = this.agv.agv
    camera.parent = agvObj.agv
    return camera
  }

  public toggleCamera(agvLabel: string) {
    if (this.scene.activeCamera === this.camera) {
      if (agvLabel === 'agv1') {
        this.scene.activeCamera = this.followCameraOne
      }
      // else if (agvLabel === 'agv2') {
      //   this.scene.activeCamera = this.followCameraTwo
      // } else {
      //   this.scene.activeCamera = this.followCameraThree
      // }
    } else {
      this.scene.activeCamera = this.camera
    }
  }


  private createArcRotateCamera() {
    const center = this.map.getGroundCenter()
    const camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(center.x, 0, center.z), this.scene);
    // fork agv
    camera.position = new BABYLON.Vector3(center.x, 65, center.z)
    // 旋转相机180度,这里很关键,后面遇到不同的地图,可能需要调整
    camera.alpha += Math.PI;
    // 获取鼠标输入管理器
    camera.attachControl(true, false, 0); // The 3 here indicates that panning will be done with button 3
    return camera
  }



  public toggleThreeCamera() {
    // fork agv
    this.camera.position.x = this.camera.position.x + 10
  }


  // private createFreeCamera() {
  //   const center = this.map.getGroundCenter()
  //   // Create a FreeCamera, and set its position to {x: 0, y: 5, z: -10}
  //   const camera = new BABYLON.FreeCamera(
  //     "camera1",
  //     new BABYLON.Vector3(center.x, 100, center.z),
  //     this.scene
  //   );

  //   // Enable mouse wheel inputs.
  //   camera.inputs.addMouseWheel();
  //   camera.inputs.removeMouse()

  //   // camera.inputs.attached.mouse.buttons = [BABYLON.MouseButton.LEFT, BABYLON.MouseButton.RIGHT];

  //   // Target the camera to scene origin
  //   camera.setTarget(
  //     new BABYLON.Vector3(center.x, 0, center.z),
  //   );
  //   // Attach the camera to the canvas
  //   camera.attachControl(this.canvas, false);
  //   return camera;
  // }


  private createAxesHelper() {
    new BABYLON.AxesViewer(this.scene, 1, 2);
  }

  // private createDirectionalLight() {
  //   //Light direction is directly down
  //   const light = new BABYLON.DirectionalLight("DirectionalLight", new BABYLON.Vector3(0, -1, 0));
  //   light.intensity = 1;
  //   return light;
  // }

  private initRender() {
    // run the render loop
    this.engine.runRenderLoop(() => {
      this.scene.render();
    });
  }

  private initResizeEvent() {
    // the canvas/window resize event handler
    window.addEventListener("resize", () => {
      // canvas 重新计算宽度和高度 
      this.canvas.width = window.innerWidth;
      this.canvas.height = window.innerHeight;
      this.engine.resize();
    });
  }

  public static getInstance(createFlag:boolean=false) {
    if (!createFlag && Base.base !== undefined) {
      return Base.base;
    }
    const oCanvas = document.createElement("canvas");
    oCanvas.style.position = "absolute";
    oCanvas.width = window.innerWidth;
    oCanvas.height = window.innerHeight;
    Base.base = new Base(oCanvas as HTMLCanvasElement);
    return Base.base;
  }


  private registerMoveX() {
    EE.on('moveX', (x: number) => {
      this.scene.meshes.forEach(function (mesh) {
        mesh.position.x += x;
      });
    })

  }





}